package bb.lanxing.calc.processer;

import android.text.TextUtils;

import com.github.mikephil.charting.utils.Utils;

import bb.lanxing.App;
import bb.lanxing.R;
import bb.lanxing.calc.PointChecker;
import bb.lanxing.calc.calculator.ElevationGradeCalc;
import bb.lanxing.calc.calculator.GpsLostCalc;
import bb.lanxing.calc.calculator.IntervalCalc;
import bb.lanxing.calc.calculator.PTElevationGradeCalc;
import bb.lanxing.calc.calculator.PaceCalc;
import bb.lanxing.calc.calculator.PauseCalc;
import bb.lanxing.calc.calculator.PowerAnalyzer;
import bb.lanxing.calc.data.CadencePoint;
import bb.lanxing.calc.data.DisplayPoint;
import bb.lanxing.calc.data.GpsPoint;
import bb.lanxing.calc.data.HeartratePoint;
import bb.lanxing.calc.data.PowerratePoint;
import bb.lanxing.calc.data.IndoorbikePoint;
import bb.lanxing.calc.data.BiketrainerPoint;
import bb.lanxing.calc.data.CrosstrainerPoint;
import bb.lanxing.calc.data.RowerPoint;
import bb.lanxing.calc.data.PowerData;
import bb.lanxing.calc.data.SourcePoint;
import bb.lanxing.calc.data.SourcePointPair;
import bb.lanxing.calc.fixer.AltitudeCorrector;
import bb.lanxing.calc.fixer.AltitudeFixer;
import bb.lanxing.calc.fixer.SpeedFixer;
import bb.lanxing.calc.manager.SourceDataPool;
import bb.lanxing.calc.notify.SpeedAlert;
import bb.lanxing.calc.notify.TFTTSChecker;
import bb.lanxing.calc.processer.i.IWorkoutProcessor;
import bb.lanxing.manager.RemoteSharedPreference;
import bb.lanxing.manager.SPConstant;
import bb.lanxing.model.WorkoutDatabaseHelper;
import bb.lanxing.model.database.Segment;
import bb.lanxing.model.database.Trackpoint;
import bb.lanxing.model.database.User;
import bb.lanxing.model.database.Workout;
import bb.lanxing.model.json.CadenceSection;
import bb.lanxing.model.json.HeartrateSection;
import bb.lanxing.util.CalorieUtil;
import bb.lanxing.util.CyclingPowerUtil;
import bb.lanxing.util.DistanceUtil;
import bb.lanxing.util.DurationUtil;
import bb.lanxing.util.Enums;

import bb.lanxing.util.WorkoutTitleUtil;
import android.util.Log;

import java.util.UUID;

public abstract class BaseWorkoutProcessor implements IWorkoutProcessor {
	final static private String TAG = "BaseWorkoutProcessor";
	private static final float MIN_STORE_DISTANCE = 0.0f;
	private static final int MIN_STORE_DURATION = 0;
	protected AltitudeCorrector altitudeCorrector;
	protected AltitudeFixer altitudeFixer;
	protected DisplayPoint displayPoint;
	protected ElevationGradeCalc elevationGradeCalc;
	protected GpsLostCalc gpsLostCalc;
	protected IntervalCalc intervalCalc;
	protected PaceCalc paceCalc;
	protected PauseCalc pauseCalc;
	protected PointChecker pointChecker;
	protected PowerAnalyzer powerAnalyzer;
	protected PTElevationGradeCalc ptElevationGradeCalc;
	private SourceDataPool sourceDataPool;
	protected SourcePointPair sourcePointPair;
	protected SpeedAlert speedAlert;
	protected SpeedFixer speedFixer;
	protected TFTTSChecker ttsChecker;
	protected Workout workout;
	protected boolean isLastCrash = false;
	protected Trackpoint lastTrackpoint = null;
	protected boolean filterEnable = true;
	private int cadenceCount = 0;
	private int cadencePointCount = 0;
	private int heartrateCount = 0;
	private int powerrateCount = 0;
	private double indoorbikespeedCount = 0;
	private int indoorbikeheartrateCount = 0;
	private int indoorbikecadenceCount = 0;
	private int indoorbikepowerCount = 0;
	private int indoorbikeenergyCount = 0;
	private double indoorbikedistanceCount = 0;
	private int indoorbikeenergyBase = 0;
	private double indoorbikedistanceBase = 0;
	private int heartratePointCount = 0;
	private int powerratePointCount = 0;
	private int indoorbikespeedPointCount = 0;
	private int indoorbikeheartratePointCount = 0;
	private int indoorbikecadencePointCount = 0;
	private int indoorbikepowerPointCount = 0;
	private int indoorbikeenergyPointCount = 0;
	private int indoorbikedistancePointCount = 0;
	private double crosstrainerspeedCount = 0;
	private int crosstrainercadenceCount = 0;
	private int crosstrainerpowerCount = 0;
	private int crosstrainerenergyCount = 0;
	private double crosstrainerdistanceCount = 0;
	private int crosstrainerstrideCount = 0;
	private int crosstrainerenergyBase = 0;
	private double crosstrainerdistanceBase = 0;
	private int crosstrainerstrideBase = 0;
	private int crosstrainerspeedPointCount = 0;
	private int crosstrainercadencePointCount = 0;
	private int crosstrainerpowerPointCount = 0;
	private int crosstrainerenergyPointCount = 0;
	private int crosstrainerdistancePointCount = 0;
	private int crosstrainerstridePointCount = 0;
	private int rowerpowerCount = 0;
	private int rowercadenceCount = 0;
	private double rowerdistanceCount = 0;
	private double rowerdistanceBase = 0;
	private int rowerpowerPointCount = 0;
	private int rowercadencePointCount = 0;
	private int rowerdistancePointCount = 0;
	private int rowerenergyBase = 0;
	private int rowerenergyPointCount = 0;
	private int rowerenergyCount = 0;
	private int biketrainerpowerCount = 0;
	private int biketrainerpowerPointCount = 0;
	private int biketrainercadenceCount = 0;
	private int biketrainercadencePointCount = 0;
	protected boolean userInitiatedPause = false;

	@Override public abstract boolean checkPoint(SourcePoint sourcePoint);

	@Override public void flushPoint(boolean sync) {
	}

	@Override public void initConfigs() {
	}

	@Override public abstract DisplayPoint process(SourcePoint sourcePoint);

	@Override public void storePoint(SourcePoint sourcePoint) {
	}

	@Override public void updateConfigs(String key, Object value) {
	}

	@Override public void init(String uuid) {
		init(SourceDataPool.DEFAULT_TYPES, null, uuid);
	}

	@Override public void init() {
		init(SourceDataPool.DEFAULT_TYPES, null);
	}

	@Override public void init(int[] dataTypes) {
		init(dataTypes, null);
	}

	@Override public void init(int[] dataTypes, Workout lastWorkout) {
		initCalc();
		initConfigs();
		initPace(lastWorkout);
		initWorkout(lastWorkout, UUID.randomUUID().toString());
		initSourceDataPool(dataTypes, lastWorkout);
	}

	@Override public void init(int[] dataTypes, Workout lastWorkout, String uuid) {
		initCalc();
		initConfigs();
		initPace(lastWorkout);
		initWorkout(lastWorkout, uuid);
		initSourceDataPool(dataTypes, lastWorkout);
	}

	@Override public void release() {
		releaseWorkout();
		releaseCalc();
		releaseSourceDataPool();
	}

	@Override public void pauseSportByUser(boolean pause) {
		userInitiatedPause = pause;
	}

	@Override public void filterPoint(boolean filter) {
		filterEnable = filter;
	}

	private void initPace(Workout lastWorkout) {
		if (lastWorkout != null) {
			paceCalc.initEachInfo(lastWorkout);
		}
	}

	private void initWorkout(Workout lastWorkout, String uuid) {
		boolean z = false;
		if (lastWorkout == null) {
			isLastCrash = false;
			lastTrackpoint = null;
			workout = new Workout();
			workout.setUuid(uuid);
			workout.setUserId(App.getContext().getUserId());
			workout.setStartTime(0L);
			workout.setEndTime(0L);
			workout.setDistance(Utils.DOUBLE_EPSILON);
			workout.setDuration(0L);
			workout.setSport(RemoteSharedPreference.getInstance().getInt(SPConstant.KEY_SPORT_TYPE, Workout.TYPE_CYCLING));
			workout.setWorkStatus(Workout.STATUS_GPS_SEARCHING);//16
			workout.setPowerFTP(getFtpVal());
			WorkoutDatabaseHelper.save(workout);//permission not granted
			Log.d(TAG, "SAVE workout. id=" + workout.getId());
			return;
		}
		if (lastWorkout.getWorkStatus() != Workout.STATUS_STOPED && lastWorkout.getLocSource() == Workout.LOCATION_SOURCE_PHONE) {//32
			z = true;
		}
		isLastCrash = z;
		Trackpoint queryLastTrackPoint = WorkoutDatabaseHelper.queryLastTrackPoint(lastWorkout.getId());
		lastTrackpoint = queryLastTrackPoint;
		if (queryLastTrackPoint != null) {
			queryLastTrackPoint.setPointType(isLastCrash ? Trackpoint.POINT_TYPE_CRASH : Trackpoint.POINT_TYPE_FINISH);
			WorkoutDatabaseHelper.save(lastTrackpoint);
			//TODO:sunj
			//            App.getContext().uploadUnfinishedInfoToUmeng(UmengEventConst.WORKOUT_FAILED, workout);
		}
		workout = lastWorkout;
		lastWorkout.setUploadStatus(Enums.UploadStatus.NotUpload);
		workout.setRealtimeSpeed(Utils.DOUBLE_EPSILON);
		workout.setWorkStatus(Workout.STATUS_GPS_SEARCHING);//16
		workout.setPowerFTP(getFtpVal());
		WorkoutDatabaseHelper.save(workout);
		Segment.createSegment(workout);
	}

	public void initSourceDataPool(int[] dataTypes, Workout lastWorkout) {
		if (dataTypes == null) {
			dataTypes = SourceDataPool.DEFAULT_TYPES;
		}
		sourceDataPool = new SourceDataPool(dataTypes);
		sourceDataPool.init(lastWorkout);
	}

	private static float getFtpVal() {
		User signinUser = App.getContext().getSigninUser();
		if (signinUser == null || signinUser.getPowerFTP() <= 0.0f) {
			return 200.0f;
		}
		return signinUser.getPowerFTP();
	}

	private void releaseWorkout() {
		Log.d(TAG, "releaseWorkout... workout=" + workout);
		if (workout == null) {
			return;
		}

		Log.d(TAG, "releaseWorkout... distance=" + workout.getDistance());
		if (workout.getDistance() > Utils.DOUBLE_EPSILON || (workout.getSport() == Workout.TYPE_TRAINING && workout.getDuration() > 0) || (workout.getSport() == Workout.TYPE_INDOOR_BIKE && workout.getDuration() > 0) || (workout.getSport() == Workout.TYPE_BIKE_TRAINER && workout.getDuration() > 0) || (workout.getSport() == Workout.TYPE_ROWER && workout.getDuration() > 0) || (workout.getSport() == Workout.TYPE_CROSS_TRAINER && workout.getDuration() > 0)) {
			workout.setWorkStatus(Workout.STATUS_STOPED);//32
			SourcePoint curSourcePoint = sourcePointPair.getCurSourcePoint();
			paceCalc.calcEachKMInfo(workout, curSourcePoint);
			workout.setSegmentKM(null);
			if (workout.getMaxHeartrate() > 0) {
				HeartrateSection heartrateSection = new HeartrateSection();
				heartrateSection.init(workout);
				workout.setSegmentHr(heartrateSection.toJsonString());
			}
			if (workout.getMaxCadence() > 0) {
				CadenceSection cadenceSection = new CadenceSection();
				cadenceSection.init(workout);
				workout.setSegmentCa(cadenceSection.toJsonString());
			}
			if (TextUtils.isEmpty(workout.getTitle())) {
				workout.setTitle(WorkoutTitleUtil.buildWorkoutDefaultTitle(App.getContext(), workout));
			}
			if (curSourcePoint != null) {
				workout.setEndTime(Math.max(workout.getEndTime(), curSourcePoint.getTimestamp()));
			}
			long vDuration = (workout.getEndTime() - workout.getStartTime()) / 1000;
			if (workout.getDuration() > vDuration) {
				workout.setDuration(vDuration);
			}
			flushPoint(true);
			Log.d(TAG, "releaseWorkout... before calcPower...vDuration=" + vDuration);
			calcPower(workout);
			WorkoutDatabaseHelper.save(workout);
			//            if (workout.getCadenceSource() == Workout.CADENCE_SOURCE_QI) {
			//                PTAltitudeResultFixer.fix(workout.getId());
			//                return;
			//            }
			Log.d(TAG, "releaseWorkout...end of release data......");
			return;
		}
		try {
			App.getContext().showMessage(App.getContext().getString(R.string.sport_toast_too_short));
			WorkoutDatabaseHelper.delete(workout);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void calcPower(Workout workout) {
		Log.d(TAG, "calcPower...powerAnalyzer=" + powerAnalyzer);
		if (powerAnalyzer == null) {
			return;
		}
		workout.queryPowerAvgAndMax();
		Log.d(TAG, "calcPower... getMaxPower=" + workout.getMaxPower() + ", getPowerNP=" + workout.getPowerNP());
		if (workout.getMaxPower() <= Utils.DOUBLE_EPSILON || workout.getPowerNP() > Utils.DOUBLE_EPSILON) {
			return;
		}
		double normalizedPower = powerAnalyzer.getNormalizedPower();
		double d = powerAnalyzer.getIf();
		double vi2 = powerAnalyzer.getVi();
		double tss = powerAnalyzer.getTss();
		Log.d(TAG, "calcPower... normalizedPower=" + normalizedPower + ", getIf=" + d + ", getVi=" + vi2 + ", getTss=" + tss);
		workout.setPowerNP(normalizedPower);
		workout.setPowerIF(d);
		workout.setPowerVI(vi2);
		workout.setPowerTSS(tss);
	}

	@Override public void initCalc() {
		speedFixer = new SpeedFixer();
		altitudeFixer = new AltitudeFixer();
		altitudeCorrector = new AltitudeCorrector();
		gpsLostCalc = new GpsLostCalc();
		pauseCalc = new PauseCalc();
		pointChecker = new PointChecker();
		elevationGradeCalc = new ElevationGradeCalc();
		ptElevationGradeCalc = new PTElevationGradeCalc();
		paceCalc = new PaceCalc();
		ttsChecker = new TFTTSChecker();
		intervalCalc = new IntervalCalc();
		sourcePointPair = new SourcePointPair();
		displayPoint = new DisplayPoint();
		User signinUser = App.getContext().getSigninUser();
		powerAnalyzer = new PowerAnalyzer((signinUser == null || signinUser.getPowerFTP() <= 0.0f) ? 200.0f : signinUser.getPowerFTP());
	}

	@Override public void releaseCalc() {
		resetCalculator();
	}

	private void resetCalculator() {
		speedFixer.reset();
		altitudeFixer.reset();
		altitudeCorrector.release();
		gpsLostCalc.release();
		pauseCalc.release();
		pointChecker.release();
		elevationGradeCalc.reset();
		ptElevationGradeCalc.reset();
		paceCalc.reset();
		ttsChecker.release();
		intervalCalc.reset();
		sourcePointPair.release();
		displayPoint.reset();
		cadenceCount = 0;
		cadencePointCount = 0;
		heartrateCount = 0;
		heartratePointCount = 0;
		isLastCrash = false;
		lastTrackpoint = null;
		powerAnalyzer = null;
	}

	void releaseSourceDataPool() {
		if (sourceDataPool != null) {
			this.sourceDataPool = null;
		}
	}

	@Override public void calcPoint(SourcePoint sourcePoint) {
		//        Log.d(TAG, "calcPoint...");
		fixPoint(sourcePoint);
		calcRealtimeValues(sourcePoint);
		PowerAnalyzer powerAnalyzer = this.powerAnalyzer;
		//        Log.d(TAG, "calcPoint...this.powerAnalyzer=" + powerAnalyzer);
		if (powerAnalyzer != null) {
			powerAnalyzer.update((double) sourcePoint.getPower());
		}
	}

	protected void fixPoint(SourcePoint sourcePoint) {
		if (this.filterEnable) {
			this.speedFixer.fix2(sourcePoint);
			this.altitudeFixer.fix(sourcePoint);
			this.altitudeCorrector.process(sourcePoint);
		}
	}

	protected void calcRealtimeValues(SourcePoint sourcePoint) {
		float vPressure = RemoteSharedPreference.getInstance().getFloat(SPConstant.KEY_WEATHER_PRESSURE, 0.0f);
		//        Log.d(TAG, "calcRealtimeValues...vPressure=" + vPressure);
		//        if (sourcePoint.hasPressure()) {
		if (vPressure > 0.0f) { //use internet weather pressure
			ptElevationGradeCalc.calc(sourcePoint);
			float elevation = ptElevationGradeCalc.getElevation();
			float grade = ptElevationGradeCalc.getGrade();
			Log.d(TAG, "calcRealtimeValues...elevation=" + elevation + ", grade=" + grade);
			sourcePoint.setElevation(elevation);
			sourcePoint.setGrade(grade);
			CadencePoint cadencePoint = sourcePoint.getCadencePoint();
			if (cadencePoint == null) {
				Log.w(TAG, "calcRealtimeValues...cadencePoint == null");
				return;
			}
			Log.d(TAG, "calcRealtimeValues...cadencePoint.getCadence()=" + cadencePoint.getCadence());
			if (cadencePoint.getCadence() > 0) {
				float bearing = sourcePoint.hasGps() ? sourcePoint.getGpsPoint().getBearing() : 0.0f;
				float f = RemoteSharedPreference.getInstance().getFloat(SPConstant.KEY_WEATHER_WIND_SPEED, 0.0f);
				float f2 = RemoteSharedPreference.getInstance().getFloat(SPConstant.KEY_WEATHER_WIND_DEG, 0.0f);
				Log.d(TAG, "calcRealtimeValues...bearing=" + bearing + ", windspeed=" + f + ", winddeg=" + f2);
				PowerData powerData = new PowerData();
				powerData.setTemperature(cadencePoint.getRealTemperature());
				powerData.setPressure(vPressure);//cadencePoint.getRealPressure()//use internet pressure
				powerData.setSpeed((float) (cadencePoint.getSpeed() > Utils.DOUBLE_EPSILON ? cadencePoint.getSpeed() : sourcePoint.getSpeed()));
				powerData.setBearing(bearing);
				powerData.setAcceleration((float) sourcePointPair.getAcceleration());
				powerData.setWindSpeed(f);
				powerData.setWindDeg(f2);
				powerData.setGrade(grade);
				powerData.setTrainingMode(isTrainingMode());
				sourcePoint.setPower(CyclingPowerUtil.calcRealtimePower(powerData));
				sourcePoint.setPowerExt(powerData.getPowerExtar());
			}
		} else {
			elevationGradeCalc.calc(sourcePoint);
			float elevation2 = elevationGradeCalc.getElevation();
			float grade2 = elevationGradeCalc.getGrade();
			sourcePoint.setElevation(elevation2);
			sourcePoint.setGrade(grade2);
		}
		sourcePoint.setDistanceEach(sourcePointPair.getDistance());
		sourcePoint.setDurationEach(sourcePointPair.getDuration());
	}

	@Override public void calcWorkout(SourcePoint sourcePoint) {
		double newAddDistance = 0;
		int duration0;
		double speedGap = 0;
		//        int calcCalorieWithPower = 0;
		float elevation;
		float grade;
		long timestamp = sourcePoint.getTimestamp();
		Log.d(TAG, "calcWorkout ...");
		if (isLastCrash && sourcePoint.hasGps()) {
			isLastCrash = false;
		}
		if (lastTrackpoint == null) {
			lastTrackpoint = new Trackpoint();
		}
		if (lastTrackpoint != null) {
			if (timestamp - lastTrackpoint.getTime() <= 3600000) {
				if (sourcePoint.getLatLng() != null) {
					newAddDistance = DistanceUtil.get(sourcePoint.getLatLng(), lastTrackpoint.getLatLng());
				}
				duration0 = (int) DurationUtil.get(timestamp, lastTrackpoint.getTime());
				speedGap = sourcePoint.getSpeed() - lastTrackpoint.getSpeed();
			} else {
				newAddDistance = MIN_STORE_DISTANCE;
				duration0 = MIN_STORE_DURATION;
				speedGap = 0.0d;
			}
			if (sourcePoint.getLatLng() != null) {
				lastTrackpoint.setLatitude(sourcePoint.getLatLng().latitude);
			}
			if (sourcePoint.getLatLng() != null) {
				lastTrackpoint.setLongitude(sourcePoint.getLatLng().longitude);
			}
			lastTrackpoint.setTime(timestamp);
			if (workout.getStartTime() == 0) {
				workout.setStartTime(timestamp);
			}
			workout.setEndTime(timestamp);
			setWorkoutSource(workout, sourcePoint);
			if (newAddDistance <= Utils.DOUBLE_EPSILON) {
				newAddDistance = sourcePointPair.getValidDistance();
			}
			workout.addDistance(newAddDistance);
			ttsChecker.checkTtsNotifyByDistance(workout);
			long duration = duration0 <= 0 ? sourcePointPair.getDuration() : duration0;
			workout.addDuration(1);
			ttsChecker.checkTtsNotifyByDuration(workout);
			if (sourcePoint.getSpeed() > workout.getMaxSpeed()) {
				workout.setMaxSpeed(sourcePoint.getSpeed());
			}
			workout.setAvgSpeed(workout.getDuration() > 0 ? workout.getDistance() / workout.getDuration() : 0.0d);
			if (workout.getAvgSpeed() > workout.getMaxSpeed()) {
				workout.setAvgSpeed(workout.getMaxSpeed() * 0.9d);
			}
			workout.setRealtimeSpeed(workout.getAvgSpeed());
			if (speedAlert != null) {
				speedAlert.checkSpeed(sourcePoint.getSpeed());
			}
			if (speedGap <= Utils.DOUBLE_EPSILON) {
				speedGap = newAddDistance / duration;
			}
			Log.d(TAG, "calcWorkout source point power=" + sourcePoint.getPower());
			float vPower = sourcePoint.getPower();
			if (vPower <= 0.0f) {
				vPower = CyclingPowerUtil.estPower(sourcePoint.getSpeed(), duration, speedGap, sourcePoint.getGrade(), sourcePoint.getElevation());
			}
			Log.d(TAG, "calcWorkout vPower=" + vPower);
			//            calcCalorieWithPower = CalorieUtil.calcCalorieWithPower(vPower, duration);
			//            Log.d(TAG, "calcWorkout calcCalorieWithPower=" + calcCalorieWithPower);
			//            workout.addCalorie(calcCalorieWithPower);
			if ((workout.getSport() == Workout.TYPE_TRAINING) || (workout.getSport() == Workout.TYPE_INDOOR_BIKE) || (workout.getSport() == Workout.TYPE_BIKE_TRAINER) || (workout.getSport() == Workout.TYPE_ROWER) || (workout.getSport() == Workout.TYPE_CROSS_TRAINER)) {
				Log.d(TAG, "IT IS TYPE_TRAINING");
			} else {
				Log.d(TAG, "IT IS NOT TYPE_TRAINING");
				double vCalorie = CalorieUtil.calcCalorieBMR(workout.getSport(), workout.getDistance(), workout.getDuration());
				workout.setCalorie((int) vCalorie);
			}

			paceCalc.calcEachKMInfo(workout, sourcePoint);

			elevation = sourcePoint.getElevation();
			if (elevation >= 0.0f) {
				workout.addElevationGain(elevation);
			} else if (elevation < 0.0f) {
				workout.addElevationLoss(-elevation);
			}

			grade = sourcePoint.getGrade();
			workout.setGrade(grade);
			Log.d(TAG, "calcWorkout elevation=" + elevation + ", grade=" + grade);
			if (grade >= 2.0f) {
				workout.addUpDistance(newAddDistance);
				workout.addUpDuration(duration);
			} else if (grade < -2.0f) {
				workout.addDownDistance(newAddDistance);
				workout.addDownDuration(duration);
			} else {
				workout.addFlatDistance(newAddDistance);
				workout.addFlatDuration(duration);
			}
			if (grade > workout.getMaxGrade()) {
				workout.setMaxGrade((int) grade);
			}
			if (grade < workout.getMinGrade()) {
				workout.setMinGrade((int) grade);
			}
			workout.setStep(sourcePoint.getSteps());
			Log.d(TAG, "calcWorkout workout.getStep()=" + workout.getStep());
			processBleData(workout, sourcePoint);
			sourcePoint.setDistance(workout.getDistance());
			sourcePoint.setDuration(workout.getDuration());
			sourcePoint.setElevationGain(workout.getElevationGain());
			sourcePoint.setElevationLoss(workout.getElevationLoss());
		}
	}

	public boolean isTrainingMode() {
		return workout != null && workout.getSport() == Workout.TYPE_TRAINING;
	}

	public boolean isIndoorBikeMode() {
		return workout != null && workout.getSport() == Workout.TYPE_INDOOR_BIKE;
	}

	public boolean isBikeTrainerMode() {
		return workout != null && workout.getSport() == Workout.TYPE_BIKE_TRAINER;
	}

	public boolean isRowerMode() {
		return workout != null && workout.getSport() == Workout.TYPE_ROWER;
	}

	public boolean isCrossTrainerMode() {
		return workout != null && workout.getSport() == Workout.TYPE_CROSS_TRAINER;
	}

	public boolean isGpsLost(SourcePoint sourcePoint) {
		return gpsLostCalc.isGpsLost(sourcePoint);
	}

	public boolean isSamePoints(SourcePoint sourcePoint) {
		return sourcePoint.isOldPoint();
	}

	public boolean isPaused(SourcePoint sourcePoint) {
		return pauseCalc.isPaused(sourcePoint);
	}

	public boolean checkPointValid(SourcePoint sourcePoint) {
		return pointChecker.isValid(sourcePoint);
	}

	public void setWorkoutSource(Workout workout, SourcePoint sourcePoint) {
		if (workout == null || sourcePoint == null) {
			return;
		}
		GpsPoint gpsPoint = sourcePoint.getGpsPoint();
		if (gpsPoint != null) {
			workout.setLocSource(gpsPoint.getSource());
		}
		CadencePoint cadencePoint = sourcePoint.getCadencePoint();
		if (cadencePoint != null) {
			workout.setCadenceSource(cadencePoint.getSource());
			if (cadencePoint.getSource() == Workout.CADENCE_SOURCE_QI) {
				workout.setPowerSource(Workout.POWER_SOURCE_QI);
			}
		}
		HeartratePoint heartratePoint = sourcePoint.getHeartratePoint();
		if (heartratePoint != null) {
			workout.setHeartSource(heartratePoint.getSource());
		}

		PowerratePoint powerratePoint = sourcePoint.getPowerratePoint();
		if (powerratePoint != null) {
			workout.setPowerSource(powerratePoint.getSource());
		}

		IndoorbikePoint indoorbikePoint = sourcePoint.getIndoorbikePoint();
		if (indoorbikePoint != null) {
			workout.setPowerSource(Workout.POWER_SOURCE_OTHER);
		}

		CrosstrainerPoint crosstrainerPoint = sourcePoint.getCrosstrainerPoint();
		if (crosstrainerPoint != null) {
			workout.setPowerSource(Workout.POWER_SOURCE_OTHER);
		}

		RowerPoint rowerPoint = sourcePoint.getRowerPoint();
		if (rowerPoint != null) {
			workout.setPowerSource(Workout.POWER_SOURCE_OTHER);
		}
	}

	private Enums.RoadType getRoadType(int grade) {
		if (grade > 1) {
			return Enums.RoadType.Up;
		}
		if (grade < -1) {
			return Enums.RoadType.Down;
		}
		return Enums.RoadType.Flat;
	}

	public void processBleData(Workout workout, SourcePoint sourcePoint) {
		if (sourcePoint == null) {
			return;
		}

		CadencePoint cadencePoint = sourcePoint.getCadencePoint();
		if (cadencePoint != null) {
			int cadence = cadencePoint.getCadence();
			workout.setCadence(cadence);
			if (cadence > 0) {
				if (cadence > workout.getMaxCadence()) {
					workout.setMaxCadence(cadence);
				}
				int i = cadencePointCount + 1;
				cadencePointCount = i;
				int i2 = cadenceCount + cadence;
				cadenceCount = i2;
				workout.setAvgCadence(i2 / i);
			}
			int sumCadence = cadencePoint.getSumCadence();
			if (sumCadence > 0) {
				if (workout.getStartCadence() == 0) {
					workout.setStartCadence(sumCadence);
				}
				workout.setEndCadence(sumCadence);
			}
			int sumWheel = cadencePoint.getSumWheel();
			if (sumWheel > 0) {
				if (workout.getStartWheel() == 0) {
					workout.setStartWheel(sumWheel);
				}
				workout.setEndWheel(sumWheel);
			}
			int wheelRpm = cadencePoint.getWheelRpm();
			if (wheelRpm > 0 && wheelRpm > workout.getMaxWheelRevolution()) {
				workout.setMaxWheelRevolution(wheelRpm);
			}
		}

		HeartratePoint heartratePoint = sourcePoint.getHeartratePoint();
		if (heartratePoint != null) {
			int heartrate = heartratePoint.getHeartrate();
			workout.setHeartrate(heartrate);
			if (heartrate > 0) {
				workout.setHeartSource(Workout.HEARTRATE_SOURCE_BLE);
				if (heartrate > workout.getMaxHeartrate()) {
					workout.setMaxHeartrate(heartrate);
				}
				int i3 = heartrateCount + heartrate;
				heartrateCount = i3;
				int i4 = heartratePointCount + 1;
				heartratePointCount = i4;
				workout.setAvgHeartrate(i3 / i4);
			}
		}
		PowerratePoint powerratePoint = sourcePoint.getPowerratePoint();
		if (powerratePoint != null) {
			int powerrate = powerratePoint.getPowerrate();
			workout.setPowerSource(powerrate);
			if (powerrate > 0) {
				workout.setPowerSource(Workout.POWER_SOURCE_OTHER);
				if (powerrate > workout.getMaxPower()) {
					workout.setMaxPower(powerrate);
				}
				int i3 = powerrateCount + powerrate;
				powerrateCount = i3;
				int i4 = powerratePointCount + 1;
				powerratePointCount = i4;
				workout.setAvgPower((double) i3 / i4);
			}
		}

		IndoorbikePoint indoorbikePoint = sourcePoint.getIndoorbikePoint();
		if (indoorbikePoint != null) {
			double indoorbikespeed = indoorbikePoint.getIndoorbikeSpeed();
			int indoorbikecadence = indoorbikePoint.getIndoorbikeCadence();
			int indoorbikepower = indoorbikePoint.getIndoorbikePower();
			int indoorbikeenergy = indoorbikePoint.getIndoorbikeEnergy();
			double indoorbiketotaldistance = indoorbikePoint.getIndoorbikeTotalDistance();
			int indoorbikeheartrate = indoorbikePoint.getIndoorbikeHeartRate();

			if (indoorbikepower > 0) {
				workout.setPowerSource(Workout.POWER_SOURCE_OTHER);
				if (indoorbikepower > workout.getMaxPower()) {
					workout.setMaxPower(indoorbikepower);
				}
				int i3 = indoorbikepowerCount + indoorbikepower;
				indoorbikepowerCount = i3;
				int i4 = indoorbikepowerPointCount + 1;
				indoorbikepowerPointCount = i4;
				workout.setAvgPower(i3 / i4);
			}

			if (indoorbikecadence > 0) {
				workout.setCadence(indoorbikecadence);
				if (indoorbikecadence > workout.getMaxCadence()) {
					workout.setMaxCadence(indoorbikecadence);
				}
				int i5 = indoorbikecadenceCount + indoorbikecadence;
				indoorbikecadenceCount = i5;
				int i6 = indoorbikecadencePointCount + 1;
				indoorbikecadencePointCount = i6;
				workout.setAvgCadence(i5 / i6);
			}

			if (indoorbikespeed > 0) {
				if ((indoorbikespeed) > workout.getMaxSpeed()) {
					workout.setMaxSpeed(indoorbikespeed);
				}
				double i7 = indoorbikespeedCount + indoorbikespeed;
				indoorbikespeedCount = i7;
				int i8 = indoorbikespeedPointCount + 1;
				indoorbikespeedPointCount = i8;
				workout.setAvgSpeed(i7 / i8);
			}

			if (indoorbikeenergy > 0) {
				int i9 = indoorbikeenergyCount + indoorbikeenergy;
				indoorbikeenergyCount = i9;
				int i10 = indoorbikeenergyPointCount + 1;
				indoorbikeenergyPointCount = i10;
				if (i10 == 1) {
					indoorbikeenergyBase = indoorbikeenergyCount;
				}

				int indoorbikeCalories = (indoorbikeenergy - indoorbikeenergyBase) * 1000;
				Log.d(TAG, "indoorbikeeneryBase is " + indoorbikeenergyBase);
				Log.d(TAG, "indoorbikeCalories is " + indoorbikeCalories);
				workout.setCalorie(indoorbikeCalories);
			}

			if (indoorbiketotaldistance > 0) {
				double i11 = indoorbikedistanceCount + indoorbiketotaldistance;
				indoorbikedistanceCount = i11;
				int i12 = indoorbikedistancePointCount + 1;
				indoorbikedistancePointCount = i12;
				if (i12 == 1) {
					indoorbikedistanceBase = indoorbikedistanceCount;
				}

				double indoorbikedistance = indoorbiketotaldistance - indoorbikedistanceBase;
				Log.d(TAG, "indoorbikedistanceBase is " + indoorbikedistanceBase);
				Log.d(TAG, "indoorbikedistance is " + indoorbikedistance);
				workout.setDistance(indoorbikedistance);
			}

			if (indoorbikeheartrate > 0) {
				if ((indoorbikeheartrate) > workout.getMaxHeartrate()) {
					workout.setMaxHeartrate(indoorbikeheartrate);
				}
				int i13 = indoorbikeheartrateCount + indoorbikeheartrate;
				indoorbikeheartrateCount = i13;
				int i14 = indoorbikeheartratePointCount + 1;
				indoorbikeheartratePointCount = i14;
				workout.setAvgHeartrate(i13 / i14);
			}
		}

		BiketrainerPoint biketrainerPoint = sourcePoint.getBiketrainerPoint();
		if (biketrainerPoint != null) {
			int biketrainercadence = biketrainerPoint.getBiketrainerCadence();
			int biketrainerpower = biketrainerPoint.getBiketrainerPower();

			if (biketrainerpower > 0) {
				workout.setPowerSource(Workout.POWER_SOURCE_OTHER);
				if (biketrainerpower > workout.getMaxPower()) {
					workout.setMaxPower(biketrainerpower);
				}
				int i3 = biketrainerpowerCount + biketrainerpower;
				biketrainerpowerCount = i3;
				int i4 = biketrainerpowerPointCount + 1;
				biketrainerpowerPointCount = i4;
				workout.setAvgPower(i3 / i4);
			}

			if (biketrainercadence > 0) {
				workout.setCadence(biketrainercadence);
				if (biketrainercadence > workout.getMaxCadence()) {
					workout.setMaxCadence(biketrainercadence);
				}
				int i5 = biketrainercadenceCount + biketrainercadence;
				biketrainercadenceCount = i5;
				int i6 = biketrainercadencePointCount + 1;
				biketrainercadencePointCount = i6;
				workout.setAvgCadence(i5 / i6);
			}
		}

		CrosstrainerPoint crosstrainerPoint = sourcePoint.getCrosstrainerPoint();
		if (crosstrainerPoint != null) {
			double crosstrainerspeed = crosstrainerPoint.getCrosstrainerSpeed();
			int crosstrainerstride = crosstrainerPoint.getCrosstrainerStride();
			int crosstrainersteprate = crosstrainerPoint.getCrosstrainerStepRate();
			int crosstrainerpower = crosstrainerPoint.getCrosstrainerPower();
			int crosstrainerenergy = crosstrainerPoint.getCrosstrainerEnergy();
			double crosstrainertotaldistance = crosstrainerPoint.getCrosstrainerTotalDistance();

			if (crosstrainerpower > 0) {
				workout.setPowerSource(Workout.POWER_SOURCE_OTHER);
				if (crosstrainerpower > workout.getMaxPower()) {
					workout.setMaxPower(crosstrainerpower);
				}
				int i3 = crosstrainerpowerCount + crosstrainerpower;
				crosstrainerpowerCount = i3;
				int i4 = crosstrainerpowerPointCount + 1;
				crosstrainerpowerPointCount = i4;
				workout.setAvgPower(i3 / i4);
			}

			if (crosstrainersteprate > 0) {
				workout.setCadence(crosstrainersteprate);
				if (crosstrainersteprate > workout.getMaxCadence()) {
					workout.setMaxCadence(crosstrainersteprate);
				}
				int i5 = crosstrainercadenceCount + crosstrainersteprate;
				crosstrainercadenceCount = i5;
				int i6 = crosstrainercadencePointCount + 1;
				crosstrainercadencePointCount = i6;
				workout.setAvgCadence(i5 / i6);
			}

			if (crosstrainerspeed > 0) {
				if ((crosstrainerspeed) > workout.getMaxSpeed()) {
					workout.setMaxSpeed(crosstrainerspeed);
				}
				double i7 = crosstrainerspeedCount + crosstrainerspeed;
				crosstrainerspeedCount = i7;
				int i8 = crosstrainerspeedPointCount + 1;
				crosstrainerspeedPointCount = i8;
				workout.setAvgSpeed(i7 / i8);
			}

			if (crosstrainerenergy > 0) {
				int i9 = crosstrainerenergyCount + crosstrainerenergy;
				crosstrainerenergyCount = i9;
				int i10 = crosstrainerenergyPointCount + 1;
				crosstrainerenergyPointCount = i10;
				if (i10 == 1) {
					crosstrainerenergyBase = crosstrainerenergyCount;
				}

				int crosstrainerCalories = (crosstrainerenergy - crosstrainerenergyBase) * 1000;
				Log.d(TAG, "crosstrainereneryBase is " + crosstrainerenergyBase);
				Log.d(TAG, "crosstrainerCalories is " + crosstrainerCalories);
				workout.setCalorie(crosstrainerCalories);
			}

			if (crosstrainertotaldistance > 0) {
				double i11 = crosstrainerdistanceCount + crosstrainertotaldistance;
				crosstrainerdistanceCount = i11;
				int i12 = crosstrainerdistancePointCount + 1;
				crosstrainerdistancePointCount = i12;
				if (i12 == 1) {
					crosstrainerdistanceBase = crosstrainerdistanceCount;
				}

				double crosstrainerdistance = crosstrainertotaldistance - crosstrainerdistanceBase;
				Log.d(TAG, "crosstrainerdistanceBase is " + crosstrainerdistanceBase);
				Log.d(TAG, "crosstrainerdistance is " + crosstrainerdistance);
				workout.setDistance(crosstrainerdistance);
			}

			if (crosstrainerstride > 0) {
				int i13 = crosstrainerstrideCount + crosstrainerstride;
				crosstrainerstrideCount = i13;
				int i14 = crosstrainerstridePointCount + 1;
				crosstrainerstridePointCount = i14;
				if (i14 == 1) {
					crosstrainerstrideBase = crosstrainerstrideCount;
				}

				int crosstrainersteps = crosstrainerstride - crosstrainerstrideBase;
				Log.d(TAG, "crosstrainerstrideBase is " + crosstrainerstrideBase);
				Log.d(TAG, "crosstrainersteps is " + crosstrainersteps);
				workout.setStep(crosstrainersteps);
			}
		}

		RowerPoint rowerPoint = sourcePoint.getRowerPoint();
		if (rowerPoint != null) {
			double rowertotaldistance = rowerPoint.getRowerTotalDistance();
			int rowerpower = rowerPoint.getRowerPower();
			int rowerenergy = rowerPoint.getRowerEnergy();
			int rowerstrokerate = rowerPoint.getRowerStrokeRate();

			if (rowerpower > 0) {
				workout.setPowerSource(Workout.POWER_SOURCE_OTHER);
				if (rowerpower > workout.getMaxPower()) {
					workout.setMaxPower(rowerpower);
				}
				int i3 = rowerpowerCount + rowerpower;
				rowerpowerCount = i3;
				int i4 = rowerpowerPointCount + 1;
				rowerpowerPointCount = i4;
				workout.setAvgPower(i3 / i4);
			}

			if (rowerstrokerate > 0) {
				workout.setCadence(rowerstrokerate);
				if (rowerstrokerate > workout.getMaxCadence()) {
					workout.setMaxCadence(rowerstrokerate);
				}
				int i5 = rowercadenceCount + rowerstrokerate;
				rowercadenceCount = i5;
				int i6 = rowercadencePointCount + 1;
				rowercadencePointCount = i6;
				workout.setAvgCadence(i5 / i6);
			}

			if (rowerenergy > 0) {
				int i9 = rowerenergyCount + rowerenergy;
				rowerenergyCount = i9;
				int i10 = rowerenergyPointCount + 1;
				rowerenergyPointCount = i10;
				if (i10 == 1) {
					rowerenergyBase = rowerenergyCount;
				}

				int rowerCalories = (rowerenergy - rowerenergyBase) * 1000;
				Log.d(TAG, "rowerenergyBase is " + rowerenergyBase);
				Log.d(TAG, "rowerCalories is " + rowerCalories);
				workout.setCalorie(rowerCalories);
			}

			if (rowertotaldistance > 0) {
				double i11 = rowerdistanceCount + rowertotaldistance;
				rowerdistanceCount = i11;
				int i12 = rowerdistancePointCount + 1;
				rowerdistancePointCount = i12;
				if (i12 == 1) {
					rowerdistanceBase = rowerdistanceCount;
				}

				double rowerdistance = rowertotaldistance - rowerdistanceBase;
				Log.d(TAG, "rowerdistanceBase is " + rowerdistanceBase);
				Log.d(TAG, "rowerdistance is " + rowerdistance);
				workout.setDistance(rowerdistance);
			}
		}
	}

	public Trackpoint makeTrackpoint(Workout workout, SourcePoint sourcePoint) {
		Trackpoint trackpoint = sourcePoint.toTrackpoint();
		trackpoint.setWorkoutId(workout.getId());
		return trackpoint;
	}

	@Override public Workout getWorkout() {
		return workout;
	}

	/**
	 * 将 SourcePoint 转化为 DisplayPoint
	 */
	public void updateDisplayPoint(SourcePoint sourcePoint) {
		if (sourceDataPool != null) {
			sourceDataPool.update(sourcePoint, workout);
			if (displayPoint != null) {
				sourceDataPool.fillPointData(displayPoint);
				displayPoint.setupWorkout(workout);
			}
		}
	}
}
